package com.shujia.mllib

import org.apache.spark.ml.classification.{LogisticRegression, LogisticRegressionModel}
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

object Demo02Person {
  def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession
      .builder()
      .appName("Demo02Person")
      .master("local[*]")
      .config("spark.sql.shuffle.partitions", 8)
      .getOrCreate()
    // 1、读取数据 进行数据特征工程处理
    val dataDF: DataFrame = spark
      .read
      .format("libsvm")
      .load("Spark/data/mllib/data/人体指标.txt")

    dataDF.printSchema()

    // 2、将数据集切分为 训练集70% 和 测试集30%
    // 训练集 用于训练模型
    // 测试集 用于检测模型
    val splitDF: Array[Dataset[Row]] = dataDF.randomSplit(Array(0.7, 0.3))
    val trainDF: Dataset[Row] = splitDF(0)
    val testDF: Dataset[Row] = splitDF(1)
    println(trainDF.count())
    println(testDF.count())

    /**
     * 3、选择合适的模型，调整模型的参数 --> 逻辑回归
     * 根据数据有无label  --> 有监督学习 --> 根据label是连续的还是离散的 --> 分类
     * --> 回归
     * --> 无监督学习
     */

    val logisticReg: LogisticRegression = new LogisticRegression()
      .setMaxIter(10) // 设置最大的迭代次数
      .setFitIntercept(true) // 是否有截距

    // 4、将训练集带入模型进行训练 得到模型
    val logisticRegModel: LogisticRegressionModel = logisticReg.fit(trainDF)

    // 5、使用测试集测试模型 计算模型准确率
    val testPreDF: DataFrame = logisticRegModel.transform(testDF)
    testPreDF.show(false)

    import spark.implicits._
    import org.apache.spark.sql.functions._


    testPreDF
      .select(sum(when($"label" === $"prediction", 1).otherwise(0)) / count("*"))
      .show()

    // 如果准确率 符合 期望 则可以将模型 保存
    logisticRegModel.save("Spark/data/mllib/person")

    /**
     * 基于人体指标.txt数据
     * 参考https://cloud.tencent.com/developer/article/1510724
     *
     * 将label中的1当作男生
     * 将label中的0当作女生
     * 计算 精确率(Precision)和召回率(Recall)
     */

  }

}
